package com.wargame.engine;

import com.wargame.hexmap.HexagonalMap;
import com.wargame.hexmap.Offset;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;


/**
 * 根据时间推进同步算子状态
 *
 * @param thisOpr   算子对象
 * @param timestamp 时间戳，算子状态同步到该时间
 * @param allOperators 所有算子数据
 * @param map 地图对象
 * @return null
 */

public Object SynchronizeToTime(Operator thisOpr, ArrayList<HashMap<String, Object>> allOperators, double timestamp, HexagonalMap map) throws ClassNotFoundException {

    int objID = (int) thisOpr.getAttri("ObjID");
    double basicSpeed = (double) thisOpr.getAttri("BasicSpeed");
    String color = (String) thisOpr.getAttri("Color");
    String oprType = (String) thisOpr.getAttri("Type");
    HashMap<String, Integer> observeDistance = thisOpr.getAttri("ObserveDistance");
    double speed = (double) thisOpr.getAttri("Speed");
    List<int[]> movePath = (List<int[]>) thisOpr.getAttri("MovePath");
    double curPos = (double) thisOpr.getAttri("CurPos");
    int[] curHex = (int[]) thisOpr.getAttri("CurHex");
    boolean canToMove = (boolean) thisOpr.getAttri("CanToMove");
    boolean flagForceStop = (boolean) thisOpr.getAttri("FlagForceStop");
    double moveToStopRemainTime = (double) thisOpr.getAttri("MoveToStopRemainTime");
    boolean stop = (boolean) thisOpr.getAttri("Stop");
    String moveState = (String) thisOpr.getAttri("MoveState");
    int changeStateRemainTime = (int) thisOpr.getAttri("ChangeStateRemainTime");
    boolean keep = (boolean) thisOpr.getAttri("Keep");
    String targetState = (String) thisOpr.getAttri("TargetState");
    int weaponCoolTime = (int) thisOpr.getAttri("WeaponCoolTime");
    String weaponUnfoldState = (String) thisOpr.getAttri("WeaponUnfoldState");
    int weaponUnfoldTime = (int) thisOpr.getAttri("WeaponUnfoldTime");
    int keepRemainTime = (int) thisOpr.getAttri("KeepRemainTime");
    boolean stack = (boolean) thisOpr.getAttri("Stack");
    ArrayList<String> validActions = new ArrayList<String>();

    double pastTime = timestamp - thisOpr.getLastSynchronizedTime();  // 时间跨度
    //修改机动属性
    if (speed > 0 && movePath.size() > 0)// 速度大于0，有机动路径
    {
        double percetage = (double) speed / 3.6 / (double) map.getHexWidth();// 计算单位时间移动了多远（speed是km/h，除3.6得到m/s，除六角格宽度（单位为米））
        curPos += percetage * pastTime;
        if (curPos >= 1)  // 到达了下一格
        {
            curPos = 0;
            curHex = movePath.get(0);// 修改位置
            movePath.remove(0);// 修改机动路径  RemoveAt(0)
            if (movePath.size() <= 0)  // 转为停止
            {
                speed = 0;
                moveToStopRemainTime = 76;// 机动转静止倒计时
            } else// 还有没走完的机动路径
            {
                int mode;// 通行方式
                double basicSpeedTemp;// 计算速度
                if (moveState.equals("March"))// 如果是行军
                {
                    mode = 1;// 通行方式为车辆行军方式
                    int roadType = map.getNeighborRoad(new Offset(curHex), new Offset(movePath.get(0)));// 根据方向查道路类型
                    if (roadType >= 0) {
                        switch (roadType) {
                            case 1:
                                basicSpeedTemp = 40;
                                break;// 如果是乡村路（黑色线）40千米/小时
                            case 2:
                                basicSpeedTemp = 60;
                                break;// 如果是一般公路（红色线）60千米/小时
                            case 3:
                                basicSpeedTemp = 90;
                                break;// 如果是等级公路（黄色线）90千米/小时
                            default:
                                basicSpeedTemp = 0;
                                break;// 未定义的道路类型或无道路
                        }
                        if (basicSpeedTemp == 0) {
                            System.out.println("机动更新失败：算子" + objID + "行军路径有误，目标格" + movePath.get(0) + "不为道路");
                            movePath = new ArrayList<>();
                        } else
                            speed = (int) (basicSpeedTemp / map.getCost(new Offset(curHex), new Offset(movePath.get(0)), mode));// 计算速度（基础速度除通行代价）
                    } else {
                        System.out.println("机动更新失败：算子" + objID + "行军路径有误，目标格" + movePath.get(0) + "不为当前格" + curHex + "的邻格");
                        movePath = new ArrayList<>();
                    }
                } else if (moveState.equals("Normal"))// 如果是正常机动
                {
                    mode = 0;// 通行方式为车辆机动方式
                    basicSpeedTemp = basicSpeed;// 正常机动速度 (float)36
                    speed = (int) (basicSpeedTemp / map.getCost(new Offset(curHex), new Offset(movePath.get(0)), mode));// 计算速度（基础速度除通行代价）
                } else if (moveState.equals("HalfSpeed"))// 如果是半速
                {
                    mode = 0;// 通行方式为车辆机动方式
                    basicSpeedTemp = basicSpeed / 2;// 正常机动速度的一半 (float)18
                    speed = (int) (basicSpeedTemp / map.getCost(new Offset(curHex), new Offset(movePath.get(0)), mode));// 计算速度（基础速度除通行代价）
                } else {
                    System.out.println("持续机动属性更新失败：算子" + objID + "的机动状态" + moveState + "未定义，恢复为默认状态");
                    moveState = "Normal";
                    speed = 0;
                    movePath = new ArrayList<>();
                    moveToStopRemainTime = 76;// 机动转静止倒计时
                }
            }
        }
        thisOpr.SetAttri("Speed", speed);
        thisOpr.SetAttri("MovePath", movePath);
        thisOpr.SetAttri("CurPos", curPos);
        thisOpr.SetAttri("CurHex", curHex);
    }
    // 停止机动
    if (flagForceStop)// 如果被停止机动
    {
        if (speed == 0)// 如果没有在机动
        {
            if (canToMove)// 如果可以机动（75秒停止机动倒计时结束）
            {
                flagForceStop = false;// 停止机动的标志位设置为false
            }
        } else if (curPos <= 0)// 如果正在机动，且完成了当前格机动
        {
            if (movePath == null) movePath = new ArrayList<>();// 清除机动路径
            else movePath.clear();
            speed = 0;// 停止机动
            moveToStopRemainTime = 76;// 机动转停止倒计时
            canToMove = false;// 不可机动
        }
    }
    // 75秒倒计时
    if (moveToStopRemainTime > 0)  // 机动转停止倒计时
    {
        moveToStopRemainTime -= pastTime;
        if (moveToStopRemainTime <= 0)// 如果倒计时结束
        {
            canToMove = true;// 可以继续机动
            flagForceStop = false;// 停止机动的标志位设置为false
            stop = true;// 处于静止状态
        }
    }
    if (changeStateRemainTime > 0)  // 切换状态倒计时
    {
        if (keep && targetState.equals("Shelt"))    //被压制，中断掩蔽
        {
            changeStateRemainTime = 0;// 结束倒计时
            targetState = moveState;// 目标状态恢复成当前状态
        } else// 没被压制，则继续倒计时
        {
            changeStateRemainTime -= pastTime;
            if (changeStateRemainTime <= 0)// 如果倒计时结束
            {
                moveState = targetState;// 机动状态设置为目标状态
            }
        }
    }
    if (weaponCoolTime > 0)  // 武器冷却倒计时
    {
        weaponCoolTime -= pastTime;
    }
    if (weaponUnfoldTime > 0)  // 武器展开/锁定倒计时
    {
        weaponUnfoldTime -= pastTime;
        if (weaponUnfoldTime <= 0)// 倒计时结束
        {
            weaponUnfoldState = (weaponUnfoldState.equals("Unfold")) ? "Fold" : "Unfold";
        }
    }
    if (keepRemainTime > 0)//压制倒计时
    {
        keepRemainTime -= pastTime;
        if (keepRemainTime <= 0)// 倒计时结束
        {
            keep = false;// 不再被压制
        }
    }

    // 更新stack字段
    int stack_count = 0;// 记录本算子当前所在的六角格一共有多少算子
    for (HashMap<String, Object> operator : allOperators) {
        int[] other_hex = (int[]) operator.get("CurHex");

        if (curHex[0] == other_hex[0] && curHex[1] == other_hex[1])// 如果在同一个六角格
        {
            String other_color = (String) operator.get("Color");
            String other_type = (String) operator.get("Type");

            if (color.equals(other_color) && (other_type.equals("Vehicle") || other_type.equals("Infantry")))
                stack_count++;// 如果是己方地面算子，stack_count加一
        }
    }
    if (stack_count > 1) stack = true;// 如果有己方其他地面算子，则为堆叠状态
    else stack = false;// 否则不为堆叠

    // 阻塞判断
    if (speed > 0 && movePath.size() > 0)// 如果正在机动
    {
        int nextHexStackCount = 0;// 记录机动的下一个六角格有多少算子
        for (HashMap<String, Object> operator : allOperators)// 遍历态势中的算子
        {
            //是否在下一格
            int[] opHex = (int[]) operator.get("CurHex");// 获取遍历到的算子的位置
            if (opHex[0] == movePath.get(0)[0] && opHex[1] == movePath.get(0)[1]) continue;// 不在下一格，跳过
            //是否是地面算子
            String opType = (String) operator.get("Type");
            if (opType.equals("Vehicle") || opType.equals("Infantry"))// 如果是地面算子
            {
                //行军阻塞判断
                if (moveState.equals("March"))// 如果本算子是行军状态
                {
                    String opMoveState = (String) operator.get("MoveState");

                    if (opMoveState.equals("March"))//行军且静止
                    {
                        boolean opStop = (boolean) operator.get("Stop");
                        if (opStop)// 遍历到的地面算子处于行军状态，且静止
                        {
                            curPos = 0;// 行军阻塞，本算子不可继续向下一格机动
                            break;
                        }
                    } else// 如果遍历到的地面算子不处于行军状态，无论静止或者没静止，都会造成行军阻塞
                    {
                        curPos = 0;// 行军阻塞，本算子不可继续向下一格机动
                        break;
                    }
                }
                //堆叠4个阻塞判断
                String opColor = (String) operator.get("Color");
                if (color == opColor) nextHexStackCount++;// 如果遍历到的算子是己方算子，记录
            }
        }
        //六角格内已存在4个本方地面单位，则格外本方地面单位不能再进入或通过该六角格。
        if (nextHexStackCount >= 4) {
            curPos = 0;// 阻塞，本算子不可继续向下一格机动
        }
    }

    // 更新ValidActions
    // 机动判断
    boolean move_flag = true;  // 能够机动的标识
    if (speed > 0) move_flag = false;   //未停下的算子不可机动
    else if (!canToMove && moveToStopRemainTime > 0) move_flag = false;// 如果在停止机动的过程中，不可以机动
    else if (weaponUnfoldTime > 0) move_flag = false;// 如果正在展开或者锁定武器，不可以机动
    else if (changeStateRemainTime > 0)  // 如果正处于状态转换过程中
    {
        if (targetState.equals("March") || targetState.equals("Shelt")) move_flag = false;// 在转行军，或者在转掩蔽，不可以机动
        if (moveState.equals("March") && TargetState.equals("Normal")) move_flag = false;// 行军转正常机动，不可以机动
    }
    if (move_flag)// 如果可以机动
    {
        validActions.add("Move");
    }
    // 判断算子是否能射击
    boolean shoot_flag = true;  // 能射击的标识
    if (weaponCoolTime > 0) shoot_flag = false;// 如果武器在冷却，不能射击
    else if (weaponUnfoldTime > 0) shoot_flag = false;  // 武器正在展开或折叠
    else if (weaponUnfoldState.equals("Fold")) shoot_flag = false;  // 武器处于锁定状态
    else if (moveState.equals("March")) shoot_flag = false;  // 行军状态不可射击
    else if (targetState.equals("March") && changeStateRemainTime > 0) shoot_flag = false;  // 行军状态转换过程中
    if (shoot_flag)// 如果可以射击
    {
        validActions.add("Shoot");// 动作集合添加进合法动作以该动作类型为键的值中
    }

    // 更新属性
    thisOpr.setAttri("Speed", speed);
    thisOpr.setAttri("MovePath", movePath);
    thisOpr.setAttri("CurPos", curPos);
    thisOpr.setAttri("CurHex", curHex);
    thisOpr.setAttri("CanToMove", canToMove);
    thisOpr.setAttri("FlagForceStop", flagForceStop);
    thisOpr.setAttri("MoveToStopRemainTime", moveToStopRemainTime);
    thisOpr.setAttri("Stop", stop);
    thisOpr.setAttri("MoveState", moveState);
    thisOpr.setAttri("ChangeStateRemainTime", changeStateRemainTime);
    thisOpr.setAttri("Keep", keep);
    thisOpr.setAttri("TargetState", targetState);
    thisOpr.setAttri("WeaponCoolTime", weaponCoolTime);
    thisOpr.setAttri("WeaponUnfoldState", weaponUnfoldState);
    thisOpr.setAttri("WeaponUnfoldTime", weaponUnfoldTime);
    thisOpr.setAttri("KeepRemainTime", keepRemainTime);
    thisOpr.setAttri("Stack", stack);
    thisOpr.setAttri("ValidActions", validActions);

    return null;
}
